package com.gxar.quick.ar.server.base.async.sms.listener;

import com.alibaba.fastjson.JSON;
import com.aliyuncs.dysmsapi.model.v20170525.QuerySendDetailsResponse;
import com.aliyuncs.dysmsapi.model.v20170525.SendBatchSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.gxar.common.utils.DingNoticeUtils;
import com.gxar.quick.ar.server.base.async.sms.dto.BatchSmsDTO;
import com.gxar.quick.ar.server.base.async.sms.dto.SmsTemplateDTO;
import com.gxar.quick.ar.server.base.async.sms.event.AliBatchSmsEvent;
import com.gxar.quick.ar.server.base.common.enums.SmsBusinessCodeEnum;
import com.gxar.quick.ar.server.base.common.properties.SmsProperties;
import com.gxar.quick.ar.server.base.sdk.AliSmsSDK;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author linsy
 * @version 1.0
 * @created 2024/3/6 09:35
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AliBatchSmsListener implements ApplicationListener<AliBatchSmsEvent> {

    private final SmsProperties smsProperties;
    private static final String DEFAULT_DING_URL = "https://oapi.dingtalk.com/robot/send?access_token=306dedee223ea4c3cb84b6a55784bdff1bf91d08648866314bd541c2f63b040a";
    private static final String DEFAULT_DING_SECRET = "SEC4165eb52d908c61cb15128a1470e199d6fe0fd863d6dc9591d97867e2b00ab88";

    @Async
    @Override
    public void onApplicationEvent(AliBatchSmsEvent event) {
        if (!smsProperties.isEnable()) {
            log.info("短信通知开关已关闭");
            return;
        }
        log.info("线程[{}]-发送短信", Thread.currentThread().getName());
        if (CollectionUtils.isEmpty(event.getDtoList())) {
            log.info("没有可发短信的内容:{}", event.getBusinessCode().getName());
            return;
        }
        SmsTemplateDTO smsTemplate = getTemplateDto(event.getBusinessCode());
        List<String> signList = event.getSignList();
        List<BatchSmsDTO> dtoList = event.getDtoList();
        // 使用默认签名
        if (CollectionUtils.isEmpty(signList)) {
            signList = new ArrayList<>();
            for (BatchSmsDTO dto : dtoList) {
                signList.add(smsTemplate.getSign());
            }
        }
        List<String> phoneList = new ArrayList<>();
        List<Map<String, String>> paramList = new ArrayList<>();
        for (BatchSmsDTO smsDto : dtoList) {
            phoneList.add(smsDto.getPhone());
            List<String> param = smsDto.getParam();
            List<String> paramNames = smsTemplate.getParamName();
            for (int i = 0; i < param.size(); i++) {
                String paramName = paramNames.get(i);
                if (StringUtils.isNotBlank(paramName)) {
                    Map<String, String> paramMap = new HashMap<>();
                    paramMap.put(paramName, param.get(i));
                    paramList.add(paramMap);
                }
            }
        }
        try {
            SendBatchSmsResponse response = AliSmsSDK.batchSendSms(JSON.toJSONString(event.getSignList()), smsTemplate.getTemplateCode(), JSON.toJSONString(phoneList), paramList);
            if (response.getCode() == null) {
                String msg = event.getBusinessCode().getName() + "短信通知失败" + "\n" +
                        "请求ID：" + response.getBizId() + "\n" +
                        "短信信息：" + JSON.toJSONString(event) + "\n" +
                        "失败原因：" + "响应CODE为空";
                DingNoticeUtils.sendDingWarningMsg(msg, StringUtils.isBlank(smsTemplate.getFailUrl()) ? DEFAULT_DING_URL : smsTemplate.getFailUrl(), StringUtils.isBlank(smsTemplate.getFailSecret()) ? DEFAULT_DING_SECRET : smsTemplate.getFailSecret());
            }
            // 有可能返回OK，但是短信没有发出去，如果数量多的话，可以考虑再根据查询详情的接口查询实际发送情况。目前官方接口暂不支持批量查询
            if (!response.getCode().equals("OK")) {
                log.info("短信发送失败:{}", response.getMessage());
                String msg = event.getBusinessCode().getName() + "短信通知失败" + "\n" +
                        "请求ID：" + response.getBizId() + "\n" +
                        "短信信息：" + JSON.toJSONString(event) + "\n" +
                        "失败原因：" + response.getMessage();
                DingNoticeUtils.sendDingWarningMsg(msg, StringUtils.isBlank(smsTemplate.getFailUrl()) ? DEFAULT_DING_URL : smsTemplate.getFailUrl(), StringUtils.isBlank(smsTemplate.getFailSecret()) ? DEFAULT_DING_SECRET : smsTemplate.getFailSecret());
            } else {
                Thread.sleep(3000L);
                for (String phone : phoneList) {
                    QuerySendDetailsResponse querySendDetailsResponse = AliSmsSDK.querySendDetails(phone, response.getBizId());
                    if (querySendDetailsResponse == null || !"OK".equals(querySendDetailsResponse.getCode())) {
                        log.error("手机号:[{}]短信发送完成，查询详情失败", phone);
                        continue;
                    }
                    for (QuerySendDetailsResponse.SmsSendDetailDTO smsSendDetailDTO : querySendDetailsResponse.getSmsSendDetailDTOs()) {
                        if (StringUtils.isNotBlank(smsSendDetailDTO.getErrCode()) && !"DELIVERED".equals(smsSendDetailDTO.getErrCode())) {
                            String msg = event.getBusinessCode().getName() + "短信通知失败" + "\n" +
                                    "请求ID：" + response.getBizId() + "\n" +
                                    "短信内容：" + smsSendDetailDTO.getContent() + "\n" +
                                    "错误原因：" + smsSendDetailDTO.getErrCode() + "\n" +
                                    "手机号：" + smsSendDetailDTO.getPhoneNum() + "\n" +
                                    "模板CODE：" + smsSendDetailDTO.getTemplateCode() + "\n";
                            DingNoticeUtils.sendDingWarningMsg(msg, StringUtils.isBlank(smsTemplate.getFailUrl()) ? DEFAULT_DING_URL : smsTemplate.getFailUrl(), StringUtils.isBlank(smsTemplate.getFailSecret()) ? DEFAULT_DING_SECRET : smsTemplate.getFailSecret());
                        }
                    }
                }
            }
        } catch (ClientException | InterruptedException e) {
            String msg = event.getBusinessCode().getName() + "短信通知失败" + "\n" +
                    "短信信息：" + JSON.toJSONString(event) + "\n" +
                    "失败原因：" + e.getMessage();
            DingNoticeUtils.sendDingWarningMsg(msg, StringUtils.isBlank(smsTemplate.getFailUrl()) ? DEFAULT_DING_URL : smsTemplate.getFailUrl(), StringUtils.isBlank(smsTemplate.getFailSecret()) ? DEFAULT_DING_SECRET : smsTemplate.getFailSecret());
        }
    }

    /**
     * 获取模板
     *
     * @param businessCode 业务模型
     * @return 响应
     */
    public SmsTemplateDTO getTemplateDto(SmsBusinessCodeEnum businessCode) {
        SmsTemplateDTO smsTemplate = null;
        if (SmsBusinessCodeEnum.EXCHANGE_SEND.equals(businessCode)) {
            smsTemplate = smsProperties.getExchange();
        }
        return smsTemplate;
    }

}
